#include "ftcolordialog.h"
#include "ftcontrols.h"

QImage FTColorDialog::hue_sat_image;
bool FTColorDialog::imagesCreated = false;

FTColorDialog::FTColorDialog(QWidget *parent) :
    QWidget(parent)
{
    initialize();
}

FTColorDialog::FTColorDialog(const QColor& c, QWidget *parent) :
    QWidget(parent)
{
    initialize(c);
}


void FTColorDialog::initialize(const QColor& col)
{
    mouse_down = false;
    if ( !imagesCreated )
    {
        hue_sat_image = QImage( 360, 256, QImage::Format_RGB16 );
        for (int h = 0; h < 360; h++ )
            for (int s = 0; s < 255; s++ )
                hue_sat_image.setPixel(h, s, QColor::fromHsv(h, s, 255).rgb() );
        imagesCreated = true;
    }
    value_image = QImage( 1, 256, QImage::Format_RGB16 );
    setCurrentColor(col);
    hue_sat_rect = value_rect = preview_rect = preview_txt_rect = hue_sat_txt_rect = value_txt_rect = QRect();
    setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
    preview_text = tr("Selected Color:");

}

QSize FTColorDialog::sizeHint() const
{
    int height = FTControls::defaultHeight();
    return QSize( height*3, height*3 );
}

QSize FTColorDialog::minimumSizeHint() const
{
    return sizeHint();
}

void FTColorDialog::paintEvent(QPaintEvent *)
{
    int padding = FTControls::defaultPadding();
    QPainter painter(this);

    // Draw text:
    painter.drawText( hue_sat_txt_rect, Qt::AlignCenter, tr("Hue/Saturation:"));
    painter.drawText( value_txt_rect, Qt::AlignCenter, tr("Value:"));
    painter.drawText( preview_txt_rect, Qt::AlignCenter, preview_text);

    // Draw value:
    painter.drawRect( value_rect );
    painter.drawImage( value_rect.adjusted(1,1,-1,-1), value_image, value_image.rect() );

    // Draw hue_sat:
    painter.drawRect( hue_sat_rect );
    painter.drawImage( hue_sat_rect.adjusted(1,1,-1,-1), hue_sat_image, hue_sat_image.rect() );

    painter.save();
    painter.setPen( QPen( QColor("white"), 4));
    int v = valueToPoint();
    painter.drawLine( value_rect.left(), v, value_rect.right(), v);
    QPoint hs = hueSatToPoint();
    painter.drawLine( hs.x() - padding, hs.y(), hs.x() + padding, hs.y() );
    painter.drawLine( hs.x(), hs.y() - padding, hs.x(), hs.y() + padding );
    painter.restore();

    // Draw preview:
    painter.setBrush( _currentColor );
    painter.drawRect( preview_rect );

}

void FTColorDialog::mouseReleaseEvent(QMouseEvent *)
{
    mouse_down = false;
}

void FTColorDialog::mouseMoveEvent(QMouseEvent * me)
{
    if ( mouse_down )
        mousePressEvent(me);
}

void FTColorDialog::mousePressEvent(QMouseEvent * me)
{
    mouse_down = true;
    QPoint pos = me->pos();

    if ( hue_sat_rect.contains( pos ) )
    {
        pointToHueSat( pos );
        buildValueImage();
    }
    else if ( value_rect.contains( pos ) )
    {
        pointToValue( pos.y() );
    }
    update();
}

void FTColorDialog::resizeEvent(QResizeEvent * re)
{
    QWidget::resizeEvent( re );
    int padding = FTControls::defaultPadding();

    QFontMetrics fm(font());
    QSize textSize =  fm.size( Qt::TextSingleLine, preview_text );
    int textHeight = textSize.height();
    int preview_text_width = textSize.width();

    int w = width() - padding*3;
    int h = height() - textHeight - padding*2;
    int w80 = w*8/10;
    int w20 = w*2/10;
    int h80 = h*8/10;
    int h20 = h*2/10;

    hue_sat_txt_rect = QRect( padding, padding, w80, textHeight );
    value_txt_rect = QRect( hue_sat_txt_rect.right(), hue_sat_txt_rect.top(), w20, textHeight );

    hue_sat_rect = QRect( hue_sat_txt_rect.left(), hue_sat_txt_rect.bottom(), w80, h80 );
    value_rect = QRect( hue_sat_rect.right(), hue_sat_txt_rect.bottom(), w20, h80 );

    int preview_padding = (w - preview_text_width - h20)/2;

    preview_txt_rect = QRect( preview_padding, hue_sat_rect.bottom(), preview_text_width, h20 );
    preview_rect = QRect( preview_txt_rect.right(),hue_sat_rect.bottom() , h20, h20 );
}

QColor FTColorDialog::currentColor() const
{
    return _currentColor;
}

void FTColorDialog::setCurrentColor(const QColor& col)
{
    _currentColor = col;
    buildValueImage();
    update();
}

void FTColorDialog::buildValueImage()
{
    QColor col;
    int h = _currentColor.hue();
    int s = _currentColor.saturation();
    for ( int v = 0; v < 255; v++)
    {
        col.setHsv( h, s, v );
        value_image.setPixel( 0, 255-v, col.rgb() );
    }
}

int FTColorDialog::valueToPoint()
{
    int v = _currentColor.value();
    return value_rect.top() + (255-v) * value_rect.height() / 256;
}

void FTColorDialog::pointToValue(int y)
{
    int h = _currentColor.hue();
    int s = _currentColor.saturation();
    int v = (value_rect.height() - (y - value_rect.top())) * 256 / value_rect.height();
    v = qBound(0, v, 255);
    _currentColor.setHsv( h, s, v );
}

void FTColorDialog::pointToHueSat(const QPoint & pt)
{
    int v = _currentColor.value();
    int h = (pt.x() - hue_sat_rect.left()) * 360 / hue_sat_rect.width();
    int s = (pt.y() - hue_sat_rect.top()) * 256 / hue_sat_rect.height();
    h = qBound(0, h, 359);
    s = qBound(0, s, 255);
    _currentColor.setHsv( h, s, v );
}

QPoint FTColorDialog::hueSatToPoint()
{
    int h = _currentColor.hue();
    int s = _currentColor.saturation();
    return QPoint( hue_sat_rect.left() + h * hue_sat_rect.width() / 360,
                   hue_sat_rect.top() + s * hue_sat_rect.height() / 256 );
}
